
#ifndef __BLOCK_TRANSFER_SERVER_H
#define __BLOCK_TRANSFER_SERVER_H

#include <stdint.h>
#include <apr.h>
#include <apr_atomic.h>
#include "UDPServer.h"

#define SHA1_DIGEST_LENGTH  (0xA0 / 0x08)

/** Three sizes of data 'block'
 * 
 * 'Little' block - data in a single UDP datagram.
 * 
 * 'Big' block - data whose hashes are communicated.
 * 
 * Active region - data which is loaded from and saved to the file. */

/** This structure holds all of the data for a big block - that is all
 * the data from the packets gets put here and when the packet count
 * goes over the appropriate value and the set is full it is hashed
 * and committed 
 * 
 * @param bigblockdata The main data structure that holds all the
 * data. This is taken from packets by being memcpy'd into the
 * appropriate place.
 * 
 * @param bigblockchecksum Once the main data structure is filled, the
 * checksum (hash) goes here.
 * 
 * @param littleblocksreceived As each packet is copied in, a bit is
 * turned on in this bit vector atomically so it does not overwrite
 * data.
 *
 * @param littleblockscommitted The number of commited packet blocks is
 * written here. As this is incremented accurately with each packet,
 * this is a true representation and can be queried first to determine
 * if this structure is writable. */
typedef struct bigblock
{
   uint32_t *bigblockdata;
   uint8_t bigblockchecksum[SHA1_DIGEST_LENGTH];
   uint32_t *littleblocksreceived;
   uint32_t littleblockscommitted;
} BigBlock;

/** This structure holds an active region in a file currently being
 * transferred. An active region is partitioned into many
 * hashed big blocks, that are each verified by comparison to hashes held
 * here. On verification, the blocks are copied back to the file.
 * 
 * @param localmp The local memory pool for this active region, so that once
 * the slot is completed or forgotten all memory can be released
 * easily.
 * 
 * @param filename The filename of the file that is being transferred
 * into.
 * 
 * @param file_offset The offset of the active block being worked on by
 * this slot inside the file.
 * 
 * @param activeregion_id The ID of the block being worked on by this
 * slot. Any packet wanting to deposit a payload inside the active
 * block must have this ID in its header.
 * 
 * @param active Whether this slot is to be considered live. This is
 * the first variable queried before deciding whether to add a packet
 * into the structure, or when looking for a new slot to activate
 * (reusing the memory).
 * 
 * @param file_blocklength The length of the active region this represents.
 * In the instance of this being the end of the file, this does not match the
 * length given in the initialiser. This allows for
 * less padding, and no zero packets to need to be sent in order for a
 * slot to complete.
 * 
 * @param littleblockcounter A counter of the number of little blocks.
 * 
 * @param verified_bit_vector A bit vector wherein each bit represents
 * one hashed block. If the hashed block has been matched successfully
 * and written back to the file, the corresponding bit is set.
 * 
 * @param hashes An array containing the list of hashes for each of
 * the hashed blocks in turn.
 * 
 * @param hashblock Structures containing the hashed blocks. */
typedef struct activeregion
{
   apr_pool_t *localmp;
   char *filename;
   uint64_t file_offset;
   uint32_t activeregion_id;
   uint32_t active;
   uint32_t file_blocklength;
   uint32_t littleblockcounter;
   uint32_t *bigblocksverified;
   uint8_t *bigblockhashes;
   BigBlock *bigblock;
} ActiveRegion;

typedef struct communication
{
   UDPSend *sender;
   CongestionControl *congestion;
   char *remotehost;
   int remoteport;
   int usec_timeout;
} Communication;

#define BLOCK_TRANSFER_SERVER__SUCCESS                 0
#define BLOCK_TRANSFER_SERVER__ALL_SLOTS_IN_USE        1
#define BLOCK_TRANSFER_SERVER__REQUESTED_BLOCK_TOO_BIG 2
#define BLOCK_TRANSFER_SERVER__FILE_UNALLOCATED        3
#define BLOCK_TRANSFER_SERVER__BLOCK_BEYOND_FILE_END   4
#define BLOCK_TRANSFER_SERVER__FILE_READ_ERROR         5
#define BLOCK_TRANSFER_SERVER__FILE_WRITE_ERROR        6
#define BLOCK_TRANSFER_SERVER__FILE_SEEK_ERROR         7
#define BLOCK_TRANSFER_SERVER__MEMORY_ERROR            8
#define BLOCK_TRANSFER_SERVER__FILE_NAME_ERROR         9
#define BLOCK_TRANSFER_SERVER__INVALID_BLOCK_ID        10

/** Server for writing UDP blocks to files. Does not have to have
 * reliability to function. */
class BlockTransferServer : public UDPServer
{
   public:
      BlockTransferServer(int inoofthreads, int iportno, const char *ihostname,
         apr_pool_t *upperpool, int inomemfileblocks, int64_t ibytes_per_second);
      ~BlockTransferServer();
   private:
      APRMutex communications_lock;
};

#endif
